package com.miyu.system.service.menu.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.blinkfox.fenix.specification.FenixSpecification;
import com.miyu.plugins.utils.Comutils;
import com.miyu.system.dao.menu.SysMenuDao;
import com.miyu.system.dao.menu.SysSpaceDao;
import com.miyu.system.pojo.system.SysMenu;
import com.miyu.system.pojo.system.SysParamConfig;
import com.miyu.system.pojo.system.SysSpace;
import com.miyu.system.service.menu.SysMenuService;
import com.miyu.system.service.system.SystemService;
import com.miyu.system.utils.enumeration.R;
import com.miyu.system.utils.stool.SystemStatic;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.Comparator;
import java.util.List;


/**0
 * 系统菜单服务impl
 *
 * @author longm
 * &#064;date  2022/10/04
 */
@Service
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class SysMenuServiceImpl implements SysMenuService {


    private final SysMenuDao dao;
    private final SysSpaceDao spaceDao;
    private final SystemService systemService;
    /**
     * 系统菜单编辑
     *
     * @param menu
     * @return {@link SysMenu }
     */
    @Override
//    @CacheEvict(cacheNames = "system:menu", key="#menu.getMenuId()",beforeInvocation=true)
    public SysMenu sysMenuEdit(SysMenu menu) {
        if(StrUtil.isNotBlank(menu.getMenuId())){
            //直接修改
            return dao.saveOrUpdateByNotNullProperties(menu);
        }
        //默认排序0
        menu.setOrderNum(menu.getOrderNum()==null?0: menu.getOrderNum());
        //获取菜单编码规则
        SysParamConfig spc = systemService.querySysConfigByCode(SystemStatic.SYS_MENU_CODE);
        String[] split = spc.getParamSet().split("-");//规则编码设置2-2-2-2 结构
        /*无父级菜单 模块顶级*/
        /*显示区域不能为空*/
        SysSpace  sp  = spaceDao.findById(menu.getSpaceId()).orElse(null);
        if(StrUtil.isBlank(menu.getParentId())) {
            menu.setParentId("-1");
            menu.setOrderNum(1);
            if (sp != null) {
                menu.setMenuCode(sp.getMenuIde() + SystemStatic.SYS_MENU_INIT_CODE);
            }
        }else{
            /*父级菜单信息*/
             SysMenu parent = dao.findById(menu.getParentId()).orElse(null);
            //父级菜单不为空 更新父级菜单为非末级菜单
            String newMenuCode="";
            if (parent != null) {
                List<SysMenu> list = dao.findAll(FenixSpecification.of(builder->
                        builder.andEquals("parentId",menu.getParentId()).build()), Sort.by("menuCode")) ;
                if(!list.isEmpty()){
                    /*循环取出需要填充的编码*/
                    for (int i = 0; i < list.size(); i++) {
                        String menuCode = list.get(i).getMenuCode();
                        //取最后两位转int
                        int code = Integer.valueOf(menuCode.substring(menuCode.length()-2)) ;
                        if((i+1)!=code){
                            //填充数据
                            if((i+1)<10){
                                newMenuCode = parent.getMenuCode()+"0"+(i+1);
                            }else{
                                newMenuCode = parent.getMenuCode()+(i+1);
                            }
                        }
                    }
                    if(StrUtil.isBlank(newMenuCode)){
                        if(list.size()+1>=10){
                            newMenuCode = parent.getMenuCode()+(list.size()+1);
                        }else{
                            newMenuCode = parent.getMenuCode()+("0"+(list.size()+1));
                        }
                    }


                }
            }else {
                if(StrUtil.isBlank(newMenuCode)){
                    newMenuCode =  parent.getMenuCode()+("01");
                }
            }

            menu.setMenuCode(newMenuCode);
        }
        return dao.save(menu);
    }

    /**
     * 查询菜单
     * 单独查询不做缓存
     * @param params 参数个数
     * @return {@link JSONArray}
     */
    @Override
    public JSONArray queryMenu(JSONObject params) {
        return dao.queryMenu(params);
    }

    /**
     * del系统菜单
     * @param sysMenus 系统菜单
     * @return jsonobject
     */
    @Override
    @CacheEvict(value="system:menu",key = "#sysMenus.menuId" )
    public JSONObject delSysMenu(SysMenu sysMenus) {
        dao.delete(sysMenus);
        return R.result("101");
    }

    @Override
    public JSONArray getSysMenuByAuthority(JSONObject params) {

       //  System.out.println(StpUtil.isLogin());
       // //登录用户数据
       // System.out.println(StpUtil.getExtra("userInfo"));
       // System.out.println(StpUtil.getPermissionList());
       //  SysUser SysUser= JSONObject.parseObject(StpUtil.getTokenInfo().getTokenValue(),SysUser.class) ;
       //  //当前登录账户
       //  System.out.println(SysUser);
        StringBuffer sql = new StringBuffer();
        sql.append("select cm.*,cs.* ");
        sql.append(" from  sys_menu cm "  );
        sql.append(" left join sys_space cs on cm.space_id = cs.space_id ");
        sql.append(" where cs.space_zone ='home'");
        JSONArray menus = dao.queryJSONArrayBySql(sql.toString());
//        //递归获取菜单
        JSONArray menuTree = new JSONArray();
        getRouterMenu(menuTree, menus);

        return menuTree;
    }

    /**
     * 查询系统菜单(菜单主界面查询)
     * 树状结构
     * @param params 参数个数
     * @return {@link JSONArray}
     */
    @Override
    public JSONArray querySysMenu(JSONObject params) {
        JSONArray menuList = dao.queryMenu(params);
        JSONArray menuTree = new JSONArray();
        getMenu(menuTree, menuList);
        System.out.println(menuTree);
        return menuTree;
    }

    /**
     * 获取树状菜单
     *
     * @param menuTree 菜单树
     * @param menus    菜单
     */
    private void getMenu(JSONArray menuTree, JSONArray menus) {
        for (int i = 0; i < menus.size(); i++) {
            JSONObject menu = menus.getJSONObject(i);
            if(menu.getString("parentId").equals("-1")){
                JSONArray rs = getChildList(menu.getString("menuId"),menus);
                if(!rs.isEmpty()){
                    menu.put("children",rs);
                }
                menuTree.add(menu);
            }
        }
        /*一级菜单排序*/
        menuTree.sort(Comparator.comparing(obj -> ((JSONObject) obj).getInteger("orderNum")));
    }

    /**
     * 获取路由 加入到缓存中
     * 菜单路由不需要树状菜单
     * @return {@link JSONArray}
     */



    @Override
    @Cacheable(value  = "system:menu:routes",key="'routes'")
    public JSONArray getRoutes() {
        return dao.getRoutes();
    }

    /**
     * 获取cos系统菜单通过权威
     * 左侧菜单查询 （ cos）
     * @param params params
     * @return jsonarray
     */
    @Override
    @Cacheable(cacheNames  = "system:menu",key="'cosMenu'")
    public JSONArray getCosMenuByAuthority(JSONObject params) {
        StringBuffer sql = new StringBuffer();
        sql.append(" select menu_id,file_path,  CONCAT('#',router_path )url  , menu_icon, menu_name label,menu_name,router_path,menu_code,ss.space_name,ss.space_zone,order_num ,ss.space_id,");
        sql.append(" parent_id");
        sql.append(" from sys_menu sm left join  sys_space ss on ss.space_id=sm.space_id ");
        sql.append(" where space_zone = 'home'");
        sql.append(" order by ss.space_id,order_num  ");
        JSONArray menus = dao.queryJSONArrayBySql(sql.toString());
        //        //递归获取菜单
        JSONArray menuTree = new JSONArray();
        getRouterMenu(menuTree, menus);

        return menuTree;

    }

    /**
     * 按空间 ID 获取菜单列表
     *
     * @param params 参数
     * @return {@link JSONArray }
     */
    @Override
    public JSONArray getMenuListBySpaceId(JSONObject params) {
        JSONArray menuTree = new JSONArray();
        if (params.containsKey("spaceId")) {
            String spaceId = params.getString("spaceId");
            List<SysMenu> menus = dao.findAll(FenixSpecification.of(builder ->
                    builder.andEquals("spaceId", spaceId).build()));
            //树状数据转换
            JSONArray menuList = JSONArray.parseArray(JSON.toJSONString(menus));
            getMenu(menuTree, menuList);
        }
        return menuTree;
    }

    /**
     * 获取子菜单+排序
     * @param menuId 菜单id
     * @param menus  菜单
     * @return {@link JSONArray}
     */
    private JSONArray getChildList(String menuId, JSONArray menus) {
        JSONArray rs = new JSONArray();
        for (int i = 0; i < menus.size(); i++) {
            JSONObject menu = menus.getJSONObject(i);
            if (menu.getString("parentId").equals(menuId)) {
                JSONArray menuList = getChildList(menu.getString("menuId"),menus);
                if (!menuList.isEmpty()) {
                    menu.put("children",menuList);
                }
                rs.add(menu);
                rs.sort(Comparator.comparing(obj -> ((JSONObject) obj).getInteger("orderNum")));
            }
        }
        return rs;
    }

    /**
     * 获取路由器菜单
     * @param menuTree 菜单树
     * @param menus    菜单
     * @return {@link JSONArray}
     */
    private JSONArray getRouterMenu(JSONArray menuTree, JSONArray menus) {
        for (int i = 0; i < menus.size(); i++) {
            JSONObject menu = menus.getJSONObject(i);
            //一级菜单 菜单父级和域名相同
            if(menu.getString("parentId").equals("-1")){
                JSONArray rs = getRouterChildList(menu.getString("menuId"),menus);
                if(!rs.isEmpty()){
                    menu.put("children",rs);
                }
                JSONObject mate = new JSONObject();
                mate.put("title", menu.getString("menuName"));
                menu.put("mate",mate);
                menu.put("path",menu.getString("pathAll"));
                menu.remove("url");
                menuTree.add(menu);
            }
        }
        /*一级菜单排序*/
        menuTree.sort(Comparator.comparing(obj -> ((JSONObject) obj).getInteger("orderNum")));
        return menuTree;
    }

    /**
     * 获取路由器孩子列表
     * 获取子菜单+排序
     * @param menuId 菜单id
     * @param menus  菜单
     * @return {@link JSONArray}
     */
    private JSONArray getRouterChildList(String menuId, JSONArray menus) {
        JSONArray rs = new JSONArray();
        for (int i = 0; i < menus.size(); i++) {
            JSONObject menu = menus.getJSONObject(i);
            if (menu.getString("parentId").equals(menuId)) {
                JSONArray menuList = getRouterChildList(menu.getString("menuId"),menus);
                if (!menuList.isEmpty()) {
                    menu.put("children",menuList);
                    menu.remove("url");
                }
                JSONObject mate = new JSONObject();
                mate.put("title", menu.getString("menuName"));
                menu.put("mate",mate);
                menu.put("path",menu.getString("pathAll"));
                rs.add(menu);
                rs.sort(Comparator.comparing(obj -> ((JSONObject) obj).getInteger("orderNum")));
            }
        }
        return rs;
    }
}
